#region

using System;
using System.Linq;
using System.Web.Mvc;
using log4net;
using xConnected.Core.Interfaces.Service;
using xConnected.Core.Model;

#endregion

namespace xConnected.Controllers
{
    public class MessageFolderController : BaseController<MessageFolder>
    {
        protected IMessageFolderService MessageFolderService;
        protected IMessageService MessageService;
        protected IUserService UserService;
        protected const string pp = "pp";
        protected const string cp = "cp";
        protected const string pr = "pr";

        public MessageFolderController(IMessageFolderService messageFolderService, IMessageService messageService, IUserService userService)
        {
            MessageFolderService = messageFolderService;
            MessageService = messageService;
            UserService = userService;
        }

        public JsonResult List()
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var userId = UserService.GetUserByUsername(User.Identity.Name).Id;

                var folders = MessageFolderService.GetAll().Where(m => m.OwnerId == userId).OrderBy(m => m.FolderType).ToList().
                        Select(m => new
                                        {
                                            m.Created,
                                            m.Updated,
                                            m.Id,
                                            m.OwnerId,
                                            m.Name,
                                            m.FolderType,
                                            Messages =
                                        m.MessageExpertUsers.Select(mu => mu.Message).Union(
                                            m.MessageCompanyUsers.Select(mc => mc.Message)).Union(
                                                m.MessagePositionUsers.Select(mp => mp.Message)).Where(me => me.Children.Count == 0).Distinct().OrderByDescending(
                                                    me => me.Id).Select(me => new
                                                                                       {
                                                                                           me.Id,
                                                                                           me.Created,
                                                                                           me.Updated,
                                                                                           me.Subject,
                                                                                           me.Body,
                                                                                           me.IsChecked,
                                                                                           BodyShort = me.Body.Length > 50 ? me.Body.Substring(0,50) + "..." : me.Body,
                                                                                           me.AllRecipientsVisible,
                                                                                           Sender =
                                                                                                me.MessageExpertUsers.Where(mp => mp.IsSender).Select(s => new
                                                                                                        {
                                                                                                            s.Id,
                                                                                                            s.ExpertProfile.Title,
                                                                                                            s.ExpertProfile.Description,
                                                                                                            Photo = s.ExpertProfile.Photo,
                                                                                                            UserType = pp,
                                                                                                            s.IsRead,
                                                                                                            s.IsStarred,
                                                                                                            s.IsDeleted
                                                                                                        }).Union(
                                                                                                me.MessageCompanyUsers.Where(mc => mc.IsSender).Select(s => new
                                                                                                                        {
                                                                                                                            s.Id,
                                                                                                                            s.CompanyProfile.Title,
                                                                                                                            s.CompanyProfile.Description,
                                                                                                                            Photo = s.CompanyProfile.Photo,
                                                                                                                            UserType = cp,
                                                                                                                            s.IsRead,
                                                                                                                            s.IsStarred,
                                                                                                                            s.IsDeleted
                                                                                                                        })).Union(
                                                                                                me.MessagePositionUsers.Where(mc => mc.IsSender).Select(s => new
                                                                                                         {
                                                                                                             s.Id,
                                                                                                             s.Position.Title,
                                                                                                             s.Position.Description,
                                                                                                             Photo = s.Position.Photo,
                                                                                                             UserType = pr,
                                                                                                             s.IsRead,
                                                                                                             s.IsStarred,
                                                                                                             s.IsDeleted
                                                                                                         })).FirstOrDefault(),
                                                                                           Receivers =
                                                                                                me.MessageExpertUsers.Where(mp => !mp.IsSender).Select(s => new
                                                                                                        {
                                                                                                            s.Id,
                                                                                                            s.ExpertProfile.Title,
                                                                                                            s.ExpertProfile.Description,
                                                                                                            Photo = s.ExpertProfile.Photo,
                                                                                                            UserType = pp,
                                                                                                            s.IsRead,
                                                                                                            s.IsStarred,
                                                                                                            s.IsDeleted
                                                                                                        }).Union(
                                                                                                me.MessageCompanyUsers.Where(mc => !mc.IsSender).Select(s => new
                                                                                                                        {
                                                                                                                            s.Id,
                                                                                                                            s.CompanyProfile.Title,
                                                                                                                            s.CompanyProfile.Description,
                                                                                                                            Photo = s.CompanyProfile.Photo,
                                                                                                                            UserType = cp,
                                                                                                                            s.IsRead,
                                                                                                                            s.IsStarred,
                                                                                                                            s.IsDeleted
                                                                                                                        })).Union(
                                                                                                me.MessagePositionUsers.Where(mc => !mc.IsSender).Select(s => new
                                                                                                               {
                                                                                                                   s.Id,
                                                                                                                   s.Position.Title,
                                                                                                                   s.Position.Description,
                                                                                                                   Photo = s.Position.Photo,
                                                                                                                   UserType = pr,
                                                                                                                   s.IsRead,
                                                                                                                   s.IsStarred,
                                                                                                                   s.IsDeleted
                                                                                                               })),
                                                                                              Children = MessageService.GetAll().Where(cm => cm.ParentId == me.ParentId || cm.Id == me.ParentId).OrderBy(cm => cm.Id).Select(cm => new
                                                                                                                                                                                    {
                                                                                                                                                                                        cm.Id,
                                                                                                                                                                                        cm.Created,
                                                                                                                                                                                        cm.Updated,
                                                                                                                                                                                        cm.Subject,
                                                                                                                                                                                        cm.Body,
                                                                                                                                                                                        BodyShort = cm.Body.Length > 50 ? cm.Body.Substring(0, 50) + "..." : cm.Body,
                                                                                                                                                                                        cm.AllRecipientsVisible,
                                                                                                                                                                                        Sender =
                                                                                                                                                                                             cm.MessageExpertUsers.Where(mp => mp.IsSender).Select(s => new
                                                                                                                                                                                             {
                                                                                                                                                                                                 s.Id,
                                                                                                                                                                                                 s.ExpertProfile.Title,
                                                                                                                                                                                                 s.ExpertProfile.Description,
                                                                                                                                                                                                 Photo = s.ExpertProfile.Photo,
                                                                                                                                                                                                 UserType = pp,
                                                                                                                                                                                                 s.IsRead,
                                                                                                                                                                                                 s.IsStarred,
                                                                                                                                                                                                 s.IsDeleted
                                                                                                                                                                                             }).Union(
                                                                                                                                                                                             cm.MessageCompanyUsers.Where(mc => mc.IsSender).Select(s => new
                                                                                                                                                                                             {
                                                                                                                                                                                                 s.Id,
                                                                                                                                                                                                 s.CompanyProfile.Title,
                                                                                                                                                                                                 s.CompanyProfile.Description,
                                                                                                                                                                                                 Photo = s.CompanyProfile.Photo,
                                                                                                                                                                                                 UserType = cp,
                                                                                                                                                                                                 s.IsRead,
                                                                                                                                                                                                 s.IsStarred,
                                                                                                                                                                                                 s.IsDeleted
                                                                                                                                                                                             })).Union(
                                                                                                                                                                                             cm.MessagePositionUsers.Where(mc => mc.IsSender).Select(s => new
                                                                                                                                                                                             {
                                                                                                                                                                                                 s.Id,
                                                                                                                                                                                                 s.Position.Title,
                                                                                                                                                                                                 s.Position.Description,
                                                                                                                                                                                                 Photo = s.Position.Photo,
                                                                                                                                                                                                 UserType = pr,
                                                                                                                                                                                                 s.IsRead,
                                                                                                                                                                                                 s.IsStarred,
                                                                                                                                                                                                 s.IsDeleted
                                                                                                                                                                                             })).FirstOrDefault(),
                                                                                                                                                                                        Receivers =
                                                                                                                                                                                             cm.MessageExpertUsers.Where(mp => !mp.IsSender).Select(s => new
                                                                                                                                                                                             {
                                                                                                                                                                                                 s.Id,
                                                                                                                                                                                                 s.ExpertProfile.Title,
                                                                                                                                                                                                 s.ExpertProfile.Description,
                                                                                                                                                                                                 Photo = s.ExpertProfile.Photo,
                                                                                                                                                                                                 UserType = pp,
                                                                                                                                                                                                 s.IsRead,
                                                                                                                                                                                                 s.IsStarred,
                                                                                                                                                                                                 s.IsDeleted
                                                                                                                                                                                             }).Union(
                                                                                                                                                                                             cm.MessageCompanyUsers.Where(mc => !mc.IsSender).Select(s => new
                                                                                                                                                                                             {
                                                                                                                                                                                                 s.Id,
                                                                                                                                                                                                 s.CompanyProfile.Title,
                                                                                                                                                                                                 s.CompanyProfile.Description,
                                                                                                                                                                                                 Photo = s.CompanyProfile.Photo,
                                                                                                                                                                                                 UserType = cp,
                                                                                                                                                                                                 s.IsRead,
                                                                                                                                                                                                 s.IsStarred,
                                                                                                                                                                                                 s.IsDeleted
                                                                                                                                                                                             })).Union(
                                                                                                                                                                                             cm.MessagePositionUsers.Where(mc => !mc.IsSender).Select(s => new
                                                                                                                                                                                             {
                                                                                                                                                                                                 s.Id,
                                                                                                                                                                                                 s.Position.Title,
                                                                                                                                                                                                 s.Position.Description,
                                                                                                                                                                                                 Photo = s.Position.Photo,
                                                                                                                                                                                                 UserType = pr,
                                                                                                                                                                                                 s.IsRead,
                                                                                                                                                                                                 s.IsStarred,
                                                                                                                                                                                                 s.IsDeleted
                                                                                                                                                                                             }))
                                                                                                                                                                                    })
                                                                                       })
                                        });

                var inbox = MessageFolderService.GetAll().First(m => m.OwnerId == userId && m.FolderType == 0);
                var unreadMesInbox = inbox.MessageExpertUsers.Select(mp => new
                                                                                      {
                                                                                          mp.Id,
                                                                                          mp.IsRead,
                                                                                          mp.IsSender
                                                                                      }).Union(
                                                                                          inbox.MessageCompanyUsers.
                                                                                              Select(mp => new
                                                                                                               {
                                                                                                                   mp.Id,
                                                                                                                   mp.IsRead,
                                                                                                                   mp.IsSender
                                                                                                               })).Union(
                                                                                                               inbox.MessagePositionUsers.
                                                                                                               Select(mp => new
                                                                                                                            {
                                                                                                                                mp.Id,
                                                                                                                                mp.IsRead,
                                                                                                                                mp.IsSender
                                                                                                                            }));
                var unreadMesInboxCount = unreadMesInbox.Where(m => m.IsSender == false && m.IsRead == false).Count();
                var outbox = MessageFolderService.GetAll().First(m => m.OwnerId == userId && m.FolderType == 1);
                var unreadMesOutboxCount = outbox.MessageExpertUsers.Select(mp => new
                                                                                        {
                                                                                            mp.Id,
                                                                                            mp.IsRead,
                                                                                            mp.IsSender
                                                                                        }).Union(
                                                                                          inbox.MessageCompanyUsers.
                                                                                              Select(mp => new
                                                                                                              {
                                                                                                                  mp.Id,
                                                                                                                  mp.IsRead,
                                                                                                                  mp.IsSender
                                                                                                                  })).Union(
                                                                                                               inbox.MessagePositionUsers.
                                                                                                               Select(mp => new
                                                                                                                           {
                                                                                                                               mp.Id,
                                                                                                                               mp.IsRead,
                                                                                                                               mp.IsSender
                                                                                                                           })).
                                                                                                                            Where(m => m.IsSender == false && m.IsRead == false).Count();
                var trash = MessageFolderService.GetAll().First(m => m.OwnerId == userId && m.FolderType == 2);
                var unreadMesTrashCount = trash.MessageExpertUsers.Select(mp => new
                                                                                    {
                                                                                        mp.Id,
                                                                                        mp.IsRead,
                                                                                        mp.IsSender
                                                                                    }).Union(
                                                                                          inbox.MessageCompanyUsers.
                                                                                              Select(mp => new
                                                                                              {
                                                                                                  mp.Id,
                                                                                                  mp.IsRead,
                                                                                                  mp.IsSender
                                                                                              })).Union(
                                                                                                               inbox.MessagePositionUsers.
                                                                                                               Select(mp => new
                                                                                                               {
                                                                                                                   mp.Id,
                                                                                                                   mp.IsRead,
                                                                                                                   mp.IsSender
                                                                                                               })).
                                                                                                                 Where(m => m.IsSender == false && m.IsRead == false).Count();
                return Json(new {folders, unreadMesInboxCount, unreadMesOutboxCount, unreadMesTrashCount }, JsonRequestBehavior.AllowGet);
            }

            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return Json(new {Result = "ERROR", ex.Message}, JsonRequestBehavior.AllowGet);
            }
        }

        [HttpPost]
        public JsonResult Save(MessageFolder messageFolder)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var user = UserService.GetUserByUsername(User.Identity.Name);
                var foundFolder =
                    MessageFolderService.GetAll().Where(m => m.OwnerId == user.Id && m.Name == messageFolder.Name);
                if (foundFolder.Count() == 0)
                {
                    messageFolder.OwnerId = user.Id;
                    messageFolder.FolderType = 3;
                    MessageFolderService.SaveOrUpdate(messageFolder);

                    return Json("Ok", JsonRequestBehavior.AllowGet);
                }
                return Json("Error", JsonRequestBehavior.AllowGet);
            }

            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return Json(new { Result = "ERROR", ex.Message }, JsonRequestBehavior.AllowGet);
            }
        }
    }
}